#include "pathological.h"


void warning(char *msg)
{
	printf("pathological: warning: %s\n",msg);
}

void copy_material(material_t *mat, Tsprops *props)
{
	color_t black, white;

	rgb_to_color(&black,0,0,0);
	rgb_to_color(&white,1,1,1);

	// Assign a BSDF
	if((props->flags & (DRCmask | SRCmask | INmask)) == DRCmask)
		mat->bsdf = lambert_bsdf, mat->sample_bsdf = lambert_sample_bsdf;
	else if((props->flags & (DRCmask | SRCmask | INmask)) == SRCmask)
		mat->bsdf = mirror_bsdf, mat->sample_bsdf = mirror_sample_bsdf;
	else if((props->flags & (DRCmask | SRCmask | INmask)) == INmask)
		mat->bsdf = fresnel_bsdf, mat->sample_bsdf = fresnel_sample_bsdf;
	else warning("no suitable BRDF function found");

	if(props->flags & EMmask)
		mat->flags |= MAT_EMITS,
		rgb_to_color(&mat->emission,props->emission.r,props->emission.g,
			props->emission.b);
	else color_copy(&mat->emission,&black);

	if(props->flags & DRCmask)
		rgb_to_color(&mat->diffuse,props->drc.r,props->drc.g,props->drc.b);
	else color_copy(&mat->diffuse,&black);

	if(props->flags & SRCmask)
		rgb_to_color(&mat->specular,props->src.r,props->src.g,props->src.b);
	else color_copy(&mat->specular,&black);

	if(props->flags & TRCmask)
		rgb_to_color(&mat->transmit,props->trc.r,props->trc.g,props->trc.b),
		color_rcp(&mat->transmit), color_sub(&mat->transmit,&white);
	else rgb_to_color(&mat->transmit,FLT_MAX,FLT_MAX,FLT_MAX);

	if(props->flags & INmask)
		rgb_to_color(&mat->ior,props->index.r,props->index.g,props->index.b);
	else color_copy(&mat->ior,&white);
}

void create_verbatim(Tverb *verb)
{
	warning("ignoring verbatim in MSDL file");
	warning(verb->text);
}

void create_view(Tview *view)
{
	float x;
	Tpt3 u = view->up, n = view->vpn;
	vector_t uv, vv; // u and v vectors of camera space

	camera.x = view->from.x;
	camera.y = view->from.y;
	camera.z = view->from.z;
	// Normalize the view plane normal
	x = 1/sqrt(sqr(n.x) + sqr(n.y) + sqr(n.z));
	n.x *= x;
	n.y *= x;
	n.z *= x;
	// Project the up vector onto the view plane
	x = u.x*n.x + u.y*n.y + u.z*n.z;
	vv.x = u.x - x*n.x;
	vv.y = u.y - x*n.y;
	vv.z = u.z - x*n.z;
	x = 1/sqrt(sqr(vv.x) + sqr(vv.y) + sqr(vv.z));
	vv.x *= x;
	vv.y *= x;
	vv.z *= x;
	// Cross product for the last vector
	uv.x = n.y*vv.z - n.z*vv.y;
	uv.y = n.z*vv.x - n.x*vv.z;
	uv.z = n.x*vv.y - n.y*vv.x;
	// Put it all in a useful format
	camera.orgin.x = view->towards.x - view->from.x + view->window.bl.u*uv.x
		+ view->window.tr.v*vv.x;
	camera.orgin.y = view->towards.y - view->from.y + view->window.bl.u*uv.y
		+ view->window.tr.v*vv.y;
	camera.orgin.z = view->towards.z - view->from.z + view->window.bl.u*uv.z
		+ view->window.tr.v*vv.z;
	x = (view->window.tr.u - view->window.bl.u)/width;
	camera.xstep.x = x*uv.x;
	camera.xstep.y = x*uv.y;
	camera.xstep.z = x*uv.z;
	x = (view->window.bl.v - view->window.tr.v)/height;
	camera.ystep.x = x*vv.x;
	camera.ystep.y = x*vv.y;
	camera.ystep.z = x*vv.z;
}

void create_scene(Tscene *scene)
{
	warning("ignoring scene in MSDL file");
}

void create_comp(Tobject *obj, Tmatrix transform)
{
	warning("ignoring component in MSDL file");
}

void end_comp(void){}

void create_triangle(Tobject *obj, Tmatrix transform)
{
	Tpt3 n, v0, v1, v2;
	triangle_t *t = calloc(1,sizeof(triangle_t));
	t->obj.type = OBJ_TRIANGLE;
	copy_material(&t->obj.mat,&obj->sprops);

	t->obj.intersect = triangle_intersect;
	t->obj.surface_point = triangle_surface_point;
	t->obj.aabb = triangle_aabb;

	assert(obj->spec.tri.vvnfn.no_verts >= 3);
	v0 = obj->spec.tri.vvnfn.data[0];
	v1 = obj->spec.tri.vvnfn.data[1];
	v2 = obj->spec.tri.vvnfn.data[2];
	t->v.x = v0.x, t->v.y = v0.y, t->v.z = v0.z;
	t->s1.x = v1.x - v0.x, t->s1.y = v1.y - v0.y, t->s1.z = v1.z - v0.z;
	t->s2.x = v2.x - v0.x, t->s2.y = v2.y - v0.y, t->s2.z = v2.z - v0.z;
	if(obj->spec.tri.vvnfn.no_fnorms)
		n = obj->spec.tri.vvnfn.data[obj->spec.tri.vvnfn.no_verts
			+ obj->spec.tri.vvnfn.no_vnorms],
		t->n.x = n.x, t->n.y = n.y, t->n.z = n.z;
	else t->n.x = t->s1.y*t->s2.z - t->s1.z*t->s2.y,
	     t->n.y = t->s1.z*t->s2.x - t->s1.x*t->s2.z,
	     t->n.z = t->s1.x*t->s2.y - t->s1.y*t->s2.x;
	normalize_vec(&t->n);
	add_object((object_t *)t);
}

void create_polygon(Tobject *obj, Tmatrix transform)
{
	warning("ignoring polygon in MSDL file");
}

void create_sphere(Tobject *obj, Tmatrix transform)
{
	sphere_t *s = calloc(1,sizeof(sphere_t));
	memset(s,0,sizeof(sphere_t));
	s->obj.type = OBJ_SPHERE;
	copy_material(&s->obj.mat,&obj->sprops);

	s->obj.intersect = sphere_intersect;
	s->obj.surface_point = sphere_surface_point;
	s->obj.aabb = sphere_aabb;

	s->c.x = obj->spec.sph.centre.x;
	s->c.y = obj->spec.sph.centre.y;
	s->c.z = obj->spec.sph.centre.z;
	s->r = obj->spec.sph.radius;
	add_object((object_t *)s);
}

void create_cylinder(Tobject *obj, Tmatrix transform)
{
	warning("ignoring cylinder in MSDL file");
}

void create_cone(Tobject *obj, Tmatrix transform)
{
	warning("ignoring cone in MSDL file");
}

void create_disc(Tobject *obj, Tmatrix transform)
{
	warning("ignoring disc in MSDL file");
}

void create_box(Tobject *obj, Tmatrix transform)
{
	warning("ignoring box in MSDL file");
}

void create_nurb(Tobject *obj, Tmatrix transform)
{
	warning("ignoring NURB in MSDL file");
}

void create_polyhedron(Tobject *obj, Tmatrix transform)
{
	warning("ignoring polyhedron in MSDL file");
}

void create_spot_lt(Tlights *light)
{
	warning("ignoring spot light in MSDL file");
}

void create_directional_lt(Tlights *light)
{
	warning("ignoring directional light in MSDL file");
}

void create_point_lt(Tlights *lights)
{
	warning("ignoring point light in MSDL file");
}

// It told me to!
void create_problem(char *probtext, int linenumber)
{
	fprintf(stderr,"pathological: error: %s, line %i\n",probtext,linenumber);
	exit(1);
}

